iT邦幫忙

2026 iThome 鐵人賽

DAY 19
0
AI Engineering

生活中的 AI 應用:我在家用 NAS 養了一隻 Agent,幫我看盤、顧家、盯備考——30 天自架實錄系列 第 19

Day 19:濕度過高自動開除濕機——HA × Agent 從「提醒」到「閉環」

  • 分享至 

  • xImage
  •  

住在台灣的人都懂:夏天一場午後雷陣雨,室內濕度輕鬆破 70%。牆角開始長斑、衣櫃有霉味、木頭家具默默受傷。解法大家也都知道——開除濕機。問題是,誰會沒事一直盯著濕度計看?

買了溫濕度感測器之後,我確實可以打開 Home Assistant 的 App 看到每個房間的數字。HA 也不是只能看——它本來就支援自動化和情境(底下接的 HomeKit 那套也是),「濕度超過 X 就開除濕機」這種規則它做得到。真正的痛點在設定這一關:要在 App 裡一條條點觸發條件、裝置、動作,改個門檻又得翻回選單重點一次;規則一多、還想帶點脈絡(雨季才啟用、夜間換個閾值),手刻 if-then 很快就變成苦工。於是多數人裝了感測器卻懶得把自動化設起來——資料看得到,決策還是回到人身上。而人是最不可靠的排程器。

這篇要講的,是連「設定自動化」這道苦工都交給 Agent:我用一句話講需求,它把控制邏輯寫出來、跑起來;而那些邊界情況——dry-run、滯環、讀不到值當故障——是我一次次踩坑後回頭要它補上的(呼應番外篇那個「我提需求、它實作」的開發迴圈)。而且它的長相,這半年變了一次。**第一版只是每兩小時巡一次感測器、濕度超標就發 Telegram 提醒我「該開除濕機了」;第二版乾脆讓它自己把除濕機打開、乾了再關掉。**這個從「提醒」到「閉環」的轉變,本身就是我最想講的一課:很多自動化的第一步是「通知人」,但通知只是把決策推回給那個最不可靠的排程器——你。

架構:HA 管感知,Agent 管判斷與執行

先講部署形態。我的 Home Assistant 不是跑在樹莓派上,而是 NAS 的虛擬機(VM)裡——同一台機器,Docker 容器群跑 Agent 系統,VM 跑 HA OS。家裡的感測器與裝置(Aqara M2 gateway 那組)先接進 HA,讓 HA 當「單一事實來源」統一管;HA 再透過 HACS 裝的 HomeKit 橋接出去給 Apple 家庭 App,家人用手機也能直接看和控。對 Agent 這側,HA 對內網開 REST API——讀狀態、下開關都走這組 API,除濕機本身也是 HA 的一個實體(humidifier domain),同一組 API 就能開關。

所以「人看得到」的畫面其實有兩個:一個是給家人的 Apple 家庭 App,另一個是我替自己做的一頁 /devices web 儀表(就掛在放全系統儀表的那台 md-server 上),把每台裝置的即時狀態、離線卡、溫濕度與 PM2.5 趨勢攤在同一頁。這頁也是番外篇講的「我提需求、它做」長出來的——閉環當下的濕度、除濕機開關狀態,我在這頁一眼就看到,不必等 Telegram 通知。

https://ithelp.ithome.com.tw/upload/images/20260818/20182865kk96cgxVmz.png

分工的哲學是:HA 負責「知道現在幾度幾 %」,Agent 負責「所以呢?」以及「那就動手」。HA 自己也能設自動化規則(濕度 > X 就開),但那得在 App 裡手動一條條刻、而且死板;接上 Agent 之後,這些規則改由它替我寫,判斷還能帶脈絡、動作能帶紀律——它記得上次的狀態、用滯環避免頻繁開關、能把「環境狀態」跟其他資訊一起寫進生活簡報,出問題還會回頭告警。感知層和智能層分開,各自換掉都不傷對方。

第一版:巡檢 + 提醒

最初的設計很直白:一個排程 job,每兩小時把所有濕度感測器讀一遍,超過警戒線就發一則 Telegram——「主臥濕度偏高,建議開除濕機」。

**HA 的 API 很直白。**拿一個 Long-lived Access Token,就能讀所有實體狀態:

curl -s -H "Authorization: Bearer <YOUR_HA_TOKEN>" \
  http://<HA_HOST>:8123/api/states/sensor.bedroom_humidity
# → {"state": "68.4", "attributes": {"unit_of_measurement": "%"}, ...}

這一版跑起來沒問題,但用了一陣子我就發現一件事:**它每次都在提醒我去做一件它其實自己做得到的事。**除濕機是 HA 的 humidifier 實體,開關就是一個 API 呼叫。那我幹嘛每次都把決策踢回給自己?尤其我出差、睡覺、開會的時候,那則「建議開除濕機」的通知躺在那裡,牆繼續受潮。

**通知只是把決策推回給人。**如果條件明確(濕度過高就是該除濕)、動作安全(開個除濕機不會出事)、回饋清楚(濕度會降下來),那這就不該是一則提醒,而該是一個閉環。

第二版:閉環自動控制

於是我把「建議」升級成「閉環」:每台除濕機以自己內建的濕度感測器為回饋,超過開啟門檻就自動開機、低於關閉門檻就自動關機。

1. 讀取所有除濕機與它們各自的內建濕度感測器
2. 逐台判斷:
   - 濕度 ≥ 68% 且目前關著 → 開機(turn_on)
   - 濕度 ≤ 55% 且目前開著 → 關機(turn_off)
   - 落在 55%~68% 之間 → 待在原狀態,不動
3. 有實際動作或有異常 → 發 Telegram;純待機 → 安靜不吵

幾個設計決策,每一個都是踩過或想過才定下來的:

**滯環:開 68%、關 55%,中間 13% 是防抖帶。**這是全篇最重要的一個數字。如果開關用同一條線(比如都設 65%),濕度在 65% 附近抖動時,除濕機就會一分鐘開、一分鐘關,反覆啟停對機器和電費都不友善。把開啟門檻(68%)和關閉門檻(55%)分開,中間留一段 13% 的緩衝——只有真的濕到 68% 才開,一路除到 55% 才停。這就是控制系統的滯環(hysteresis),跟家裡冷氣的溫控是同一套原理。(同一招我也用在空氣品質告警:PM2.5 ≥36 才算「差」、要降到 <30 才算「恢復」——只要是有門檻、又會抖動的訊號,幾乎都需要滯環,否則邊界抖動就把人洗到靜音。)

回饋用「除濕機自己的感測器」,不是房間裡那台空氣清淨機的。同一個房間可能有好幾個濕度來源,但控制迴路的回饋,要用離控制對象最近的那個——除濕機內建的感測器,量的就是它出風口附近的濕度,是這個閉環最直接的訊號。拿房間另一頭的感測器來控,等於隔著房間調水龍頭。

只開關,不改它的目標值與模式。除濕機面板上使用者可能設了自己的目標濕度、風速、模式,我的閉環只做 turn_on / turn_off,不去改那些設定值——尊重使用者的手動意圖。不過老實說有個灰色地帶:我的 OFF 門檻設在 55%,濕度一降到 55% 就關機,等於在效果上蓋過了除濕機內建那個「一路乾到 30%」的過度除濕。所以精確講是「不改它的設定值、但會用開關覆寫它的行為結果」——這條界線我自己也覺得有點微妙,就老實擺出來。

**預設 dry-run,加 --apply 才真的動手。**這是自動化碰到實體設備時的基本禮貌:平常跑 dry-run,只讀狀態、只印出「它會怎麼做」,讓我先看它的判斷對不對;確認無誤,排程上才掛 --apply。一個會實際開關你家電器的腳本,第一次就讓它真的動手,是在拿家裡的設備賭它的邏輯沒 bug。

**還有一件同屬「碰大權限設備」的安全禮貌:token 只活在環境變數層。**HA 的 token 權限很大(能開關你家所有電器),絕不能寫死在程式碼或 prompt 裡。我的做法:token 存在容器的環境變數、由部署層注入,程式碼裡只有 os.getenv("HA_TOKEN");任何會被 LLM 讀到的檔案(含記憶日誌)都不出現 token 原文——因為那些檔會被同步、備份、甚至貼進文章(Day 26 會講我在別處犯過的憑證管理錯誤)。

一個藏在「安靜」裡的坑:待機 vs 讀不到

閉環上線後,我遇到一個很細但很致命的判斷問題:當感測器讀不到值的時候,該怎麼辦?

直覺會說「讀不到就跳過,不動作」。但這裡有個陷阱。這個 job 的設計是「純待機時安靜」——濕度落在滯環中間、不需要動作時,它不輸出任何東西,好讓每兩小時一次的排程不會洗版。問題是:「滯環內無需動作」和「感測器壞了讀不到」,如果都走『安靜跳過』這條路,就長得一模一樣。

想像一下濕季裡,某台除濕機的感測器離線了。如果程式把「讀不到」當成「無需動作」安靜跳過,結果就是:除濕機在最該開的季節悄悄地永遠不開機,而沒有任何告警——直到牆發霉我才發現。

所以我把這兩種情況嚴格分開:滯環內無需動作 → 安靜;感測器讀數無效(unavailable 或非數字)→ 當成故障,印出來、發告警、讓這輪 job 以非零狀態結束,好讓上層的健康守衛(明天的主題)看得見。「沒事」和「壞了」絕不能長成同一個樣子——這是整個監控哲學的縮影,我在溫度控制那支腳本上也踩過同一個坑,這次學乖了。

我踩過的坑:斷電之後,全家「失明」

最大的坑不在軟體,在開機順序。

某次社區計畫停電,恢復供電後 NAS 自動開機、Docker 容器全部自己爬起來、Agent 照常巡檢——然後每一次 API 呼叫都 timeout。原因:**HA 跑在 VM 裡,而 NAS 的 VM 預設不隨主機自動啟動。**主機活了,VM 還躺著。那兩天 Agent 等於瞎子:讀不到任何感測器、也開不了任何除濕機,整個閉環全數失敗,直到我出差回來手動把 VM 點開。

這件事給我兩個教訓。其一是操作面的:去 NAS 的虛擬機管理介面把 HA VM 勾成開機自動啟動(一個 checkbox 的事,但你要先知道它存在)。其二是架構面的:閉環 job 後來加了「HA 本體健康檢查」——連不上 HA 這件事本身就要發告警,而且訊息明確寫「HA 無回應,可能 VM 未啟動」。依賴的服務掛掉時,系統至少要知道自己瞎了,而不是安靜地把失敗吞掉。你有沒有發現,這跟上面感測器讀不到值是同一個原則:故障必須被看見,不能偽裝成「一切正常」。

小結+明日預告

家居整合的核心不是酷炫的聲控,是「把人從盯著看、以及盯著看還要記得動手的工作裡解放出來」:HA 感知、Agent 判斷並執行、滯環防抖、故障要出聲、斷電有預案。而最關鍵的一步,是想清楚哪些事可以從「提醒你做」升級成「我來做」——條件明確、動作安全、有回饋,就是閉環的候選人。

「連不上 HA 要告警」「感測器讀不到要當故障」這些思路,其實通往一個更大的主題:整套系統裡每個服務都可能掛,誰來看著它們?明天講我的監控與自癒設計——以前服務掛掉是家人先發現,現在是系統自己重啟自己。


🔑 這篇的關鍵字
Home Assistant × Agent 整合:從「發通知提醒人」升級到「閉環自動控制」(條件明確 + 動作安全 + 有回饋)· 連「設定自動化」本身都交給 Agent:用講需求取代在 App 手刻 if-then(呼應番外篇開發迴圈)· 滯環(hysteresis):開啟與關閉門檻分開設(除濕 開 68%/關 55%;PM2.5 ≥36 進、<30 出),防邊界抖動反覆啟停 · 控制迴路的回饋要用離控制對象最近的感測器 · 只 turn_on/turn_off、不覆寫使用者手動設定 · 預設 dry-run、--apply 才動手 · 讀不到值(unavailable)要當故障告警,不能偽裝成「待機無需動作」 · 憑證只活在環境變數層 · 依賴服務掛掉(HA VM 未啟動)要自己出聲


我是一名金融業資訊工程師,這是我半年來在家自架 AI Agent 系統的實錄。


上一篇
Day 18:一筆 $864 的假股價,差點害我做錯決策
下一篇
Day 20:服務掛了不用我管——兩層監控的自癒架構
系列文
生活中的 AI 應用:我在家用 NAS 養了一隻 Agent,幫我看盤、顧家、盯備考——30 天自架實錄22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言